#include <assert.h>

#include "Integer.h"
#include "NativeMath.h"

Integer* Integer::One = new Integer(1, 1, false);
Integer* Integer::Zero = new Integer(1, 0, false);

//
// Constructors
//

Integer::Integer(const Int32 width, const bool isSigned)
{
	_integer = newint(width, isSigned);
}

Integer::Integer(const Int32 width, const int value, const bool isSigned)
{
	_integer = newint(width, isSigned);
	assignint(value, _integer);
}

Integer::Integer(const Int32 width, const string value, const bool isSigned)
{
	_integer = newint(width, isSigned);
	assignstr(value.c_str(), _integer);
}


void Integer::Negate(Integer** result, Integer* a) {
	negate(a->_integer, (*result)->_integer); 
}

//
// Arithmetic Operations

void Integer::Add(Integer** result, Integer* a, Integer* b)
{
	add(a->_integer, b->_integer, (*result)->_integer);
}

void Integer::Subtract(Integer** result, Integer* a, Integer* b)
{
	sub(a->_integer, b->_integer, (*result)->_integer);
}

void Integer::Multiply(Integer** result, Integer* a, Integer* b)
{
	mul(a->_integer, b->_integer, (*result)->_integer);
}

//
// Logic Operations
//

void Integer::And(Integer** result, Integer* a, Integer* b)
{
	_and(a->_integer, b->_integer, (*result)->_integer);
}

void Integer::Or(Integer** result, Integer* a, Integer* b)
{
	ior(a->_integer, b->_integer, (*result)->_integer);
}

void Integer::Xor(Integer** result, Integer* a, Integer* b)
{
	_xor(a->_integer, b->_integer, (*result)->_integer);
}

void Integer::Not(Integer** result, Integer* value)
{
	_not(value->_integer, (*result)->_integer);
}

void Integer::ShiftLeft(Integer** result, Integer* value, Int32 positions)
{
	shl(value->_integer, positions, (*result)->_integer);
}

void Integer::ShiftRight(Integer** result, Integer* value, Int32 positions)
{
	shr(value->_integer, positions, (*result)->_integer);
}

//
// Miscellaneous
//

void Integer::GetBit(Integer** result, Integer* value, Int32 position)
{
  if(getbit(value->_integer, position))
  {
    (*result)->ValueCopy(Integer::One);
  } 
  else
  {
    (*result)->ValueCopy(Integer::Zero);
  }
}

void Integer::ValueCopy(const Integer* value)
{
	valuecopy(value->_integer, _integer);
}

void Integer::GetRange(Integer** result, Integer* value, Int32 from, Int32 to)
{
	getrange(value->_integer, from, to, (*result)->_integer);
}

Int32 Integer::ToInt()
{
	return toint(_integer);
}

void Integer::ToBinaryString(char* buffer, const size_t bufsize)
{
	*buffer = '\0'; // clear buffer
	tobinstr(_integer, buffer, bufsize);
}

void Integer::ToDecimalString(char* buffer, const size_t bufsize)
{
	*buffer = '\0'; // clear buffer
	todecstr(_integer, buffer, bufsize);
}

void Integer::ToHexadecimalString(char* buffer, const size_t bufsize)
{
	*buffer = '\0'; // clear buffer
	tohexstr(_integer, buffer, bufsize);
}

bool Integer::Equals(const Integer* a)
{
	return areequal(this->_integer, a->_integer);
}

bool Integer::NotEquals(const Integer* a)
{
	return !areequal(this->_integer, a->_integer);
}

bool Integer::LessThan(const Integer* a)
{
	return !isgreater(this->_integer, a->_integer);
}

bool Integer::LessThanOrEquals(const Integer* a)
{
	return !isgreater(this->_integer, a->_integer) || areequal(this->_integer, a->_integer);
}

bool Integer::GreaterThan(const Integer* a)
{
	return isgreater(this->_integer, a->_integer);
}


bool Integer::GreaterThanOrEquals(const Integer* a)
{
	return isgreater(this->_integer, a->_integer) || areequal(this->_integer, a->_integer);
}

//
// Operator overloads
//

bool Integer::operator== (const Integer& a)
{
	return areequal(this->_integer, a._integer);
}
bool Integer::operator!= (const Integer& a)
{
	return !areequal(this->_integer, a._integer);
}

bool operator== (const Integer& a, const Integer& b)
{
	return areequal(a._integer, b._integer);
}

bool operator!= (const Integer& a, const Integer& b)
{
	return !areequal(a._integer, b._integer);
}	
